package services

import (
	"context"
	"fmt"
	"github.com/golang/protobuf/ptypes/empty"
	"github.com/golang/protobuf/ptypes/wrappers"

	"kop/framework/broker"
	context2 "kop/framework/context"
	"kop/framework/errors"
	"kop/libs/redis"
	"kop/modules/api/models"
	"kop/pb"
	"kop/pb/service"
	"kop/util/errgroup"

	activityC "kop/modules/activity/client"
	awardM "kop/modules/award/models"
	buildingC "kop/modules/building/client"
	captainC "kop/modules/captain/client"
	guildC "kop/modules/guild/client"
	itemC "kop/modules/item/client"
	maidC "kop/modules/maid/client"
	moneyC "kop/modules/money/client"
	questC "kop/modules/quest/client"
	ringC "kop/modules/ring/client"
	roleC "kop/modules/role/client"
	serverC "kop/modules/server/client"
	stageC "kop/modules/stage/client"
)

type ConnectService struct {
}

// 连接服务器 将Token转换RoleID
func (h *ConnectService) Connect(ctx context.Context, req *pb.ConnectRequest) (*pb.ConnectReply, error) {

	var reply pb.ConnectReply

	var serverID = req.ServerID
	var token = ctx.Value("token").(string)
	var userID = ctx.Value("UserID").(int32)

	servers, err := serverC.GetServers()
	if err != nil {
		return &reply, err
	}

	var ok bool
	for _, v := range servers {
		if v.ServerID == serverID {
			ok = true
		}
	}

	if !ok {
		return &reply, errors.ParamError
	}

	// 角色
	reply.RoleResp = roleC.GetByUserID(userID, serverID)
	var role = reply.RoleResp.Role

	// 通知本账号多点登陆
	_ = broker.RolePublish(role.RoleID, pb.WsCode_CodeLogin, &wrappers.StringValue{Value: req.Str})

	var user = context2.NewUser(role.RoleID, serverID, 0, userID)
	ctx = context2.NewContext(user)

	guild, err := guildC.MyGuild(role.RoleID, serverID, 0)
	if err != nil {
		return &reply, err
	} else if guild != nil {
		user.GuildID = guild.GuildID
		ctx = context2.NewContext(user)
	}

	var waitGroup errgroup.Group

	// 建筑
	waitGroup.Go(func() error {

		reply.Buildings = buildingC.GetBuildings(role.RoleID)
		return nil
	})

	// 货币
	//waitGroup.Go(func() error {
	//
	//	var err error
	//	reply.MoneyResp, err = moneyC.MoneyService.Online(ctx, role)
	//
	//	return err
	//})

	// 船长
	waitGroup.Go(func() error {

		reply.Captains = captainC.GetCaptains(role.RoleID)
		return nil
	})

	// 道具
	waitGroup.Go(func() error {

		reply.Items = itemC.GetItems(ctx)
		return nil
	})

	// 魔戒
	waitGroup.Go(func() error {

		reply.Rings = ringC.GetRings(role.RoleID)
		return nil
	})

	// 侍女
	waitGroup.Go(func() error {

		reply.Maids = maidC.FriendMaids(role.RoleID)
		return nil
	})

	// 侍女约会
	waitGroup.Go(func() error {

		reply.MaidDate = maidC.GetMaidDate(role.RoleID)
		return nil
	})

	// 主线任务
	waitGroup.Go(func() error {

		var quest = questC.GetQuest(role.RoleID)
		reply.Quest = quest
		return nil
	})

	// 支线任务
	waitGroup.Go(func() error {

		reply.DailyQuests = questC.GetDailyQuests(role.RoleID)
		for _, dailyQuest := range reply.DailyQuests {
			dailyQuest.Award = awardM.RandAward(role, dailyQuest.AwardID)
		}

		return nil
	})

	// 宣言
	waitGroup.Go(func() error {

		reply.Declaration = roleC.GetDeclaration(role.RoleID)
		return nil
	})

	// 主线关卡
	waitGroup.Go(func() error {

		reply.Stage = stageC.GetStage(ctx)
		return nil
	})

	// VIP进度与奖励
	waitGroup.Go(func() error {
		var err error
		reply.Vip, err = roleC.RoleService.VIPAwards(ctx, &empty.Empty{})
		return err
	})

	// 引导进度
	waitGroup.Go(func() error {

		res, err := roleC.RoleService.GetProgress(ctx, &empty.Empty{})
		if err == nil {
			reply.Progress = res.Value
		}

		return err
	})

	if err = waitGroup.Wait(); err != nil {
		return &reply, err
	}

	var hallLevel int32
	for _, v := range reply.Buildings {
		if v.BuildingID == 100 {
			hallLevel = v.Level
		}
	}
	var moneyOnlineRequest = service.MoneyOnlineRequest{RoleID: role.RoleID, ServerID: serverID, Peerage: role.Level, HallLevel: hallLevel}
	if reply.MoneyResp, err = moneyC.MoneyService.Online(ctx, &moneyOnlineRequest); err != nil {
		return &reply, err
	}

	if success, _ := redis.TodaySet(fmt.Sprintf("login_%d", role.RoleID)); success {

		//questC.Login(role.RoleID)
		activityC.AddPoints(role.RoleID, role.ServerID, activityC.Login, 1)
	}

	// 更新个人实力
	var power int64
	for _, v := range reply.Captains {
		power += v.Power
	}

	if role.Power != power {
		role.Power = power
		roleC.UpdatePower(role.RoleID, power)
	}

	// 绑定令牌
	return &reply, models.SaveUser(token, &user)
}
